﻿namespace WatExtensions.Tests.SuperCache
{
    using System;
    using System.Net;
    using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
    using WatExtensions.SuperCache;
    
    [TestClass]
    public class WebServerFixture
    {
        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteAbsoluteUrlToProxyIncludingRequestAsTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "http://absolute.request.uri/";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format(
                "http://proxy.uri/?{0}={1}",
                WebServer.WatBrowserTargetHostQueryStringParameter,
                WebUtility.UrlEncode("http://absolute.request.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteAbsoluteUrlWithPathToProxyIncludingRequestAsTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "http://absolute.request.uri/path/to/some.file";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format("http://proxy.uri/path/to/some.file?{0}={1}", WebServer.WatBrowserTargetHostQueryStringParameter, WebUtility.UrlEncode("http://absolute.request.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteRootUrlAsSameUrlIncludingBaseUriTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "/";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format("/?{0}={1}", WebServer.WatBrowserTargetHostQueryStringParameter, WebUtility.UrlEncode("http://base.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteRootedRelativeUrlWithPathAsSameUrlIncludingTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "/path/to/some.file";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format("/path/to/some.file?{0}={1}", WebServer.WatBrowserTargetHostQueryStringParameter, WebUtility.UrlEncode("http://base.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteNonRootedRelativeUrlWithPathAsSameUrlIncludingTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "path/to/some.file";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format("path/to/some.file?{0}={1}", WebServer.WatBrowserTargetHostQueryStringParameter, WebUtility.UrlEncode("http://base.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteRelativePathAndMakeItRelativeToBaseIncludingTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/path/to/some.file");
            var requestUri = "another.file";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format("another.file?{0}={1}", WebServer.WatBrowserTargetHostQueryStringParameter, WebUtility.UrlEncode("http://base.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteSamePageAnchorWithoutChanges()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "#";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            Assert.AreEqual("#", rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteParentRelativeUrlWithPathAsSameUrlIncludingTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "../path/to/some.file";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format("../path/to/some.file?{0}={1}", WebServer.WatBrowserTargetHostQueryStringParameter, WebUtility.UrlEncode("http://base.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldRewriteSeveralParentLevelsRelativeUrlWithPathAsSameUrlIncludingTargetHostParam()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "../../../path/to/some.file";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = string.Format("../../../path/to/some.file?{0}={1}", WebServer.WatBrowserTargetHostQueryStringParameter, WebUtility.UrlEncode("http://base.uri/"));
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldNotRewriteURLsForNonHttpRequests()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "DATA://some.data";

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, null);

            // Assert
            var expectedUri = "DATA://some.data";
            Assert.AreEqual(expectedUri, rewrittenUri);
        }

        [TestMethod]
        public void ResolveTargetUri_ShouldNotRewriteURLsToBypass()
        {
            // Arrange
            var testProxyUri = new Uri("http://proxy.uri/");
            var baseUri = new Uri("http://base.uri/");
            var requestUri = "http://some.url.to/bypass/like_this_one";

            var bypassUrlPatterns = new [] { "http://some.url.to/bypass/.*" };

            // Act
            var rewrittenUri = WebServer.BuildProxyUri(testProxyUri, baseUri, requestUri, bypassUrlPatterns);

            // Assert
            var expectedUri = "http://some.url.to/bypass/like_this_one";
            Assert.AreEqual(expectedUri, rewrittenUri);
        }
    }
}
